package com.foreveross.proxyip.core.pools;

import java.util.List;

import com.dayatang.domain.InstanceFactory;
import com.foreveross.proxyip.core.BaseCode;
import com.foreveross.proxyip.core.pools.thread.CircleThread;
import com.foreveross.proxyip.core.pools.thread.chan.ChannelCheckInThread;
import com.foreveross.proxyip.core.pools.thread.chan.ChannelCheckOutThread;
import com.foreveross.proxyip.core.pools.validate.ChannelTestProxyIp;
import com.foreveross.proxyip.core.redis.PiRedisExecption;
import com.foreveross.proxyip.entity.ChannelEntity;
import com.foreveross.proxyip.entity.ProxyIpBean;
import com.foreveross.proxyip.exception.ProxyIpServiceException;
import com.foreveross.proxyip.infra.base.ddd.repository.IBaseRepository;

/**
 * 渠道池（热池）
 * @author lyq
 *
 */
public class ChannelPool extends AvailablePool  {
	
	public final static String DEFAULT_CODE = "default";
	
	public AvailablePool publicPool = null;
//	String url = null;
	public String auth = "";//口令
	public ChannelEntity channel = null;
	
	public ChannelPool(AvailablePool publicPool,ChannelEntity channel) throws NumberFormatException, PiRedisExecption{
		super(channel.getName()+"渠道池",channel.getCode());
		this.publicPool = publicPool;
		this.channel = channel.cloneInstance();
	
		redisManager.channelMaps.put(poolSign, poolIpMap);
//		this.url = channel.getValidDefaultUrl();
		this.initChannelProperty();
		super.validate = new ChannelTestProxyIp(this.poolSign, this.channel);
		initBaseCode();
		this.offerWaitTime = 0;
	
//		checkOut();
//		checkIn();
	}
	
	public void initChannelProperty(){
		super.poolName = channel.getName()+"渠道池";
		this.auth = channel.getAuth();
		this.channel.setAuth(auth);
		this.channel.setName(super.poolName);
	}
	
	public void initBaseCode() throws NumberFormatException, PiRedisExecption{
		Double max = Long.parseLong(BaseCode.getValue("CHANNEL_PROXY_MAX"))*(channel.getTimes()*100)/100;
		super.proxyMax = max.longValue(); 
		Double min = Long.parseLong(BaseCode.getValue("CHANNEL_PROXY_MIN"))*(channel.getTimes()*100)/100;
		super.proxyMin = min.longValue(); 
		super.threadMaxIpCount = Integer.parseInt(BaseCode.getValue("CHANNEL_THREAD_MAX_COUNT")); 
		super.checkInSepTime = Integer.parseInt(BaseCode.getValue("CHANNEL_IP_IN_SEP_TIME"));
		super.checkInInterval = Long.parseLong(BaseCode.getValue("CHANNEL_IN_SEPARATION_TIME"));
		super.checkOutInterval = Long.parseLong(BaseCode.getValue("CHANNEL_OUT_SEPARATION_TIME"));
		this.validate.setConfig();
	}
	
	/**
	 * ip放进池里
	 * @param ip
	 * @param proxyIpBean
	 * @throws PiRedisExecption 
	 * @throws Exception 
	 */
	public void set(ProxyIpBean proxyIpBean) throws PiRedisExecption {
		if(!poolIpMap.containsKey(proxyIpBean.getCompletionIP())){//已经存在了
			proxyIpBean.getUsingKeys().add(this.poolSign);
			poolIpMap.set(proxyIpBean.getCompletionIP());
		}
	}


	public void checkIn(){
		 CircleThread run = null;
		 Thread checkInTh = null;
				 
		try {
			for (int i = 0; i < threadNum; i++) {
				run = new ChannelCheckInThread(this);
				checkInTh = new Thread(run, this.poolSign + "-checkin-" + i);
				this.checkInThs.add(checkInTh);
				checkInTh.start();
			}
		} catch (Exception e) {
			log.error(ProxyIpServiceException.getStackTrace(e));
			System.exit(0);
		}
	}
	
	public void checkOut() {
		CircleThread run = null;
		Thread checkOutTh = null;
		// 检出线程比检入少一半
		int outThreadNum = threadNum / 2;
		outThreadNum = outThreadNum == 0  ? 1 : outThreadNum;

		try {
			for (int i = 0; i < outThreadNum; i++) {
				run = new ChannelCheckOutThread(this);
				checkOutTh = new Thread(run, this.poolSign + "-checkout-" + i);
				this.checkOutThs.add(checkOutTh);
				checkOutTh.start();
			}
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		}

	}
	
	public IBaseRepository getRepository(){
		IBaseRepository repository = InstanceFactory.getInstance(IBaseRepository.class,"channelEntityRepository");
		return repository;
	}


//	@Override
//	public List <ProxyIpBean>getCheckInList(Long num) throws Exception {
//		return this.publicPool.offerIps(num,poolSign);
//	}


	protected List<ProxyIpBean> lastProcess(List<ProxyIpBean> returnList,String poolCode) throws Exception {
		for(ProxyIpBean proxyIp:returnList){
			lastProcessAction(proxyIp,poolCode);
		}
		return returnList;
	}
	
	
	
	@SuppressWarnings("unchecked")
	public void lastProcessAction(ProxyIpBean bean,String poolCode) throws Exception{
		bean.getRefuseChannel().add(this.poolSign);//渠道池已经提供出去给外部接口，该渠道不再使用该ip
		this.remove(bean);
	}
	
	
	/**
	 * 获取需要checkIn的列表
	 * @param num
	 * @return
	 * @throws Exception 
	 */
//	public abstract List getCheckInList(Long num) throws Exception;
//	@SuppressWarnings("rawtypes")
//	public List getCheckInList(Long num) throws Exception {
//		List list = this.publicPool.offerIps(num, this.poolSign);
//		return list;
//	}
	
}
